package cn.mesmile.lock.aop;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author zb
 * @date 2020/12/1 15:31
 * @Description
 */
@Slf4j
@Aspect
@Component
@Order(10)   //order越小越是最先执行，但更重要的是最先执行的最后结束。order默认值是2147483647
public class LogAspect {

    private final String LOCK_CODE = "lockCode";

    private final RedissonClient redissonClient;

    public LogAspect(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    /**
     *  定义公共的切点
     */
    @Pointcut("@annotation(LogAction)")
    public void log(){

    }

    /**
     *  环绕通知
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around(value = "log()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String code = IdUtil.fastSimpleUUID();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
        String remoteUser = request.getRemoteUser();
//        log.info(">>>>>>>>>>>> remoteUser 远程用户：{}",remoteUser);
        String requestURI = request.getRequestURI();
//        log.info(">>>>>>>>>>>> requestURI 请求地址：{}",requestURI);
        request.setAttribute(LOCK_CODE, code);
        // 第一个参数
        String seckillId = joinPoint.getArgs()[0].toString();
        // 方法名
        String name = joinPoint.getSignature().getName();
        Class declaringType = joinPoint.getSignature().getDeclaringType();

        System.out.println(">>>>>>>>>>>>>>>>>>>> 记录日志，记录日志，记录日志");
        System.out.println(">>>>>>>>>>>>>>>>>>>> 记录日志，记录日志，记录日志");
        System.out.println(">>>>>>>>>>>>>>>>>>>> 记录日志，记录日志，记录日志");

         // 类似于  method.invoke 方法
        return joinPoint.proceed();

    }

    /**
     *  异常通知，当目标方法抛出异常时，该方法会被触发
     * @param joinPoint
     */
    @AfterThrowing(value = "log()",throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Exception e){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
        String code = (String) request.getAttribute(LOCK_CODE);
        log.info(">>>>>>>>>>  错误码：{}", code);
    }


}
